A/D変換の動作確認(2)
ソフト的な荒技を紹介(PICをSLEEP!しながらA/D変換)
眠らせてA/D変換をするって?
A/D モジュールはスリープ中も動作できます。
SLEEP 命令を実行させることで、ディジタル変換ノイズを除去することができます。変換が終了すると、GO/DONE ビットがクリアされて、結果がADRES
レジスタにロードされます。A/D モジュールがスリープ中に動作するには、A/D クロックソースをRC(ADCS1:ADCS0 = 11)に設定する必要があります。スリープ中に変換するには、GO/DONEビットをセットした後すぐにSLEEP
命令を実行します。
図1にA/D変換のフローチャートを示します。
プログラムの解説については、「プログラムの説明(2)」の項をご参照ください。
![]() |
図1.A/D変換プログラム(2) フローチャート |
(注)以下に示すプログラムには、ホームページ画面作成の都合上、空白として全角文字のスペースなどが挿入されています。したがって、下記プログラムリストをそのままコピーしてMPLABのソースファイルとされた場合には、エラーとなることがあります。
→ここをクリックして、下記のプログラムをダウンロードするようにしてください。
ファイル名:「adconv2.asm」 サイズ2.27kバイト
→ここをクリックして、下記のオブジェクトファイルをダウンロードするようにしてください。
ファイル名:「adconv2.hex」 サイズ1173バイト
プログラムリスト中、青字となっている行が、前ページのA/D変換プログラム(1)で変更された部分です。
;*********************************************************** ; A/D変換動作チェックプログラム(2) ; スリープ機能使用(A/D 割り込み使用) ; A/D変換入力端子(CH0/RA0) ; A/D変換の結果はLED点灯により確認 ; RB1(MSB),RB0,RD7,RD6,RD5,RD4,RD3,RD2,RD1,RD0(LSB) ; の10ビット ;*********************************************************** |
|
LIST P=PIC16F877 INCLUDE P16F877.INC |
;(1)プロセッサの種別指定 ;(2)インクルードファイルの指定 |
;*********************************************************** ; 変数定義とレジスタ割付 ;*********************************************************** |
|
COUNT EQU 20H ORG 0 |
;(3)ループカウンタ ;(4)プログラムの開始番地の指定 |
;*********************************************************** ; 入出力ピン初期化 ;*********************************************************** |
|
BSF STATUS,RP0 MOVLW B'10001110' MOVWF ADCON1 BSF PIE1,ADIE CLRF TRISB CLRF TRISD BCF STATUS,RP0 MOVLW B'11000001' MOVWF ADCON0 BSF INTCON,PEIE |
;(5)Bank 1 へ切替 ;(6)RA0のみアナログ、結果右詰 ;(7)ADCON1レジスタの設定 ;(7')A/D 割り込みを発生可にする ;(8)PortB 出力モードに設定 ; PortD 出力モードに設定 ;(9)Bank 0 へ戻す ; ;(10')Frc,CH0 設定, A/D on ;(11)ADCON0レジスタの設定 ;(11')周辺割り込みを発生させる |
;*********************************************************** ; メインプログラム ;*********************************************************** |
|
ADSTART BCF PIR1,ADIF CALL TIME BSF ADCON0,GO SLEEP MOVF ADRESH,W MOVWF PORTB BSF STATUS,RP0 MOVF ADRESL,W BCF STATUS,RP0 MOVWF PORTD GOTO ADSTART |
; ;(12')A/D 割り込みフラグビットをクリアする ;(12)23.2μs 一定時間待つ ; (2TAD [2×1.6μs]+アクィジション時間[20μs]) ;(13)A/D スタート ;(13')SLEEP 命令を実行 ; ;(16)A/D データ上位(データは右詰) ;(17)PortBへ A/D 結果を出力 ;(18)Bank 1 へ切替 ;(19)A/D データ下位 ;(20)Bank 0 へ戻す ;(21)PortDへ A/D 結果を出力 ;(22)A/D 変換を繰り返す |
;*********************************************************** ;23μs遅延サブルーチン(20MHzクロック時) ;*********************************************************** |
|
TIME MOVLW 25H MOVWF COUNT NOP LOOP DECFSZ COUNT,F GOTO LOOP RETURN END |
; ;(23)1サイクル 25H = 37 ;(24)1サイクル ;(25)1サイクル 微調整ダミー ; ;(26)1×(37-1)+2 = 38サイクル ;(27)2×(37-1) = 72サイクル ;(28)2サイクル ; 合計 115サイクル×0.2μs = 23μs ;(29)プログラム・ソースの終わり |
【プログラムの説明(2)】
このプログラムについて、解説を加えておきましょう。ただし、前ページで解説したプログラム(1)の説明と重複する部分は省略します。
ここではプログラムリスト中、青字となっている行を解説します。その他の行はプログラムの説明(1)をご覧ください。
(7’)A/D 割り込みを発生可にする
PIE1レジスタは周辺機能の割り込みのイネーブルビットが割り当てられています。
PIE1レジスタの6ビット目のADIEビットは、A/D変換器割り込みイネーブルビットとなっていて、
ADIE=1 :A/D変換割り込みを使用可能にする
ADIE=0 :A/D変換割り込みを発生不可にする
BSF PIE1,ADIE
「PIE1」レジスタのADIEビットを「1」にし、A/D変換割り込みを使用可能にする
(10’)Frc,CH0 設定,A/D on
SLEEPモードでA/D変換を行うため、A/D クロックソースをRC(ADCS1:ADCS0=11)にセットする必要があります。
「A/D変換の制御法」の表4.A/D変換用クロックの選択を参照してください。内部RC発振回路を使用するFrc指定の場合は、システムクロックには影響されず、2〜6μsの周波数になります。また、「A/D変換の制御法」の表1.ADCON0レジスタの機能説明表を参照してください。アナログチャネル指定ビットですが、CHSx=「000」とすることで、CH0(RA0)の指定になります。
bit7: A/D変換クロック(Frc)指定より ADCS1=「1」
bit6: A/D変換クロック(Frc)指定より ADCS0=「1」
bit5: アナログチャネルCH0(RA0)指定より、CHS2=「0」
bit4: アナログチャネルCH0(RA0)指定より、CHS1=「0」
bit3: アナログチャネルCH0(RA0)指定より、CHS0=「0」
bit2: A/D 変換ステータスビット(初期設定時は「0」としておく)
bit1: 機能なし(とりあえず「0」とでもしておく)
bit0: A/D ON ビット(A/D機能を使うので「1」としておく)
ということで、B’11000001’ (C1H)をWregにロードする。
(11’)周辺割り込みを発生させる
INTCON レジスタは割り込みの各種イネーブルおよびフラグビットが割り当てられているレジスタです。周辺機能の割り込みを使用可能にするためには、INTCONレジスタのPEIE
ビットをセットします。
INTCONレジスタの6ビット目のPEIEビットは、周辺割り込みイネーブルビットとなっていて、
PEIE=1:すべてのマスクされていない周辺機能の割り込みを使用可能にする
PEIE=0:すべての周辺機能の割り込みを使用不可にする
BSF INTCON,PEIE
「INTCON」レジスタのPEIEビットを「1」にし、周辺機能の割り込みを使用可能にする
(12’)A/D 割り込みフラグビットをクリアする
PIR1レジスタは周辺機能の割り込みのフラグビットが割り当てられています。
PIR1レジスタの6ビット目のADIFビットは、AD
コンバータ割り込みフラグビットとなっていて、
ADIF=1:A/D変換が完了した
ADIF=0:A/D変換が完了していない
BCF PIR1,ADIF
A/D変換をこれから行うため、「PIR1」レジスタのADIFビットを「0」にする。
(13’)SLEEP 命令を実行
ADCON0レジスタのGOビットをセットし、A/D変換を開始した直後に、プロセッサをSLEEPモードにします。A/D
モジュールはスリープ中も動作できます。
SLEEPにする利点は、ディジタル変換ノイズを除去することです。
A/D変換が終了すると、PIR1レジスタの6ビット目のADIFビットが「1」にセットされ、結果がADRES
レジスタにロードされます。
表1にSLEEPさせたときのA/D変換の実測結果と理論値を示します。ターゲットボードの値(実測値)と理論値を比べてみると、2V〜3Vあたりで最大2LSBの誤差があることが分かります。電圧換算すると、
2/1023×4.97V=約9.7mV程度になりました。
前ページ表2に示した通常のA/D変換動作の結果と大差ないことが確認されました。この結果から考えると、通常動作のA/D変換においてもディジタル変換ノイズの影響は小さく、わざわざSLEEPさせてクロックを止めたりしなくても通常にA/D変換機能を使えばよいことが分かりました。ただし、GNDラインを貧弱な配線にしたりすると、場合によっては、ディジタル変換ノイズの影響を受けてしまうこともあり得ます。そのときは、SLEEPさせることでノイズの除去効果が期待できると思います。(しかし私の考えとしては、こんなソフト的な荒技を使うより、まず第一に配線パターンを改善した方がよろしいかと思いますが。。。(^^;)
A/D変換 入力電圧 ( )内は実測値 |
出力結果 | |||||
ターゲットボード | 理論値 | |||||
2進 | 16進 | 10進 | 2進 | 16進 | 10進 | |
5V (4.97V) |
B’1111111111’ | H’3FF’ | D’1023’ | B’1111111111’ | H’3FF’ | D’1023’ |
4V (4.00V) |
B’1100111000’ | H’338’ | D’824’ | B’1100110111’ | H’337’ | D’823’ |
3V (3.001V) |
B’1001101000’ | H’268’ | D’616’ | B’1001101010’ | H’26A’ | D’618’ |
2V (2.001V) |
B’0110011010’ | H’19A’ | D’410’ | B’0110011100’ | H’19C’ | D’412’ |
1V (1.001V) |
B’0011001101’ | H’0CD’ | D’205’ | B’0011001110’ | H’0CE’ | D’206’ |
0V (0.000V) |
B’0000000000’ | H’000’ | D’000’ | B’0000000000’ | H’000’ | D’000’ |
次へは、「多入力のA/D変換法」について解説します。
![]() |
![]() |
![]() |